/*
*  Impp - Instant Messenger
*
*  Copyright (C) 2008  Oliver Schneider
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef BUDDYTREELIST_H_
#define BUDDYTREELIST_H_

#include "../../core/Buddy.h"
#include "../../core/database/DBModule.h"
#include "GroupTreeItem.h"
#include "BuddyTreeItem.h"
#include "../../core/events/StatusEvent.h"
#include "../../core/events/AvatarChangedEvent.h"
#include "../../core/events/BuddyChangedEvent.h"
#include "../../core/events/GroupChangedEvent.h"
#include "../../core/events/MessageEvent.h"
#include "../../core/events/MessageReadEvent.h"
#include "../StdUserInterfaceModule/EntryToolTip.h"
#include <wx/dcbuffer.h>
#include <wx/graphics.h>


namespace Impp {

class GroupTreeItem;

class BuddyTreeList : public wxScrolledWindow
{

private:
	struct TreeItemPosition{
		TreeItem* item;
		wxPoint pos;

		TreeItemPosition(TreeItem* item,wxPoint pos) :
			item(item),pos(pos){}
	};

private:
	DBModule dbModule;

	GroupTreeItem* rootWithGroups;
	GroupTreeItem* rootNoGroups;
	GroupTreeItem* offlineBuddies;

	std::vector<TreeItemPosition> displayedItems;
	TreeItem* selected;

	wxPoint startPos;
	wxSize fullSize;
	wxSize lastFullSize;

	wxSize groupSize;
	wxSize buddySize;

	wxFont buddyFont;
	wxFont groupFont;

	wxColor textColor;
	wxColor textColorHighlight;

	wxBrush bg;
	wxBrush bgHighlight;

	wxBitmap groupIsExpanded;
	wxBitmap groupNotExpanded;

	int indent;
	bool showOffline;
	bool useGroups;
	bool showAvas;
	bool hideEmptyGroups;
	bool treatUnknownAsOffline;
	bool dimIdle;

	BuddyPriority shownPriority;

	EntryToolTip* toolTip;


public:
	BuddyTreeList(wxPanel* parent, long id);
	virtual ~BuddyTreeList();


	void addGroup(Group* group);


	void removeBuddy(Buddy* buddy);

	void onBuddyStatusChanged(StatusEvent & event);
	void onAvatarChanged(AvatarChangedEvent & event);
	void onBuddyChanged(BuddyChangedEvent & event);
	void onGroupChanged(GroupChangedEvent & event);
	void onMessageIn(MessageEvent & event);
	void onMessageRead(MessageReadEvent & event);

	void onPaint(wxPaintEvent& evt);
	void onMouseDown(wxMouseEvent& event);
	void onMouseMoved(wxMouseEvent& event);
	void onKeyDown(wxKeyEvent& event);

	void updateBuddyCustomName(Buddy* buddy);

	void setShowOffline(bool show);
	void setUseGroups(bool use);
	void setShowAvas(bool show);
	void setHideEmptyGroups(bool hide);
	void setDimIdle(bool dim);
	void setShowBuddiesWithPriority(BuddyPriority priority);

	void OnEraseBackground(wxEraseEvent & event);
	void refreshBuddy(Buddy* buddy);

	wxBitmap getExpandedIcon(bool extended);

private:
	void addBuddy(Buddy* buddy, Group* subGroup);

	void refreshTreeItem(TreeItem* item);
	void setSelected(TreeItem* item);
	void addBuddyTreeItemToRightGroup(BuddyTreeItem* bti);
	void paintBuddyTreeItem(wxGCDC & dc,BuddyTreeItem* bti,const wxPoint& pos);
	void paintGroupTreeItem(wxGCDC & dc,GroupTreeItem* gti,const wxPoint& pos);
	TreeItem* getTreeItem(wxPoint& pos, wxPoint& itemPos);
	TreeItem* getTreeItem(GroupTreeItem* gti, wxPoint& pos, wxPoint& startPoint);
	GroupTreeItem* getGroupTreeItem(Group* g, GroupTreeItem* gti);
	bool shouldDraw(GroupTreeItem* gti);
	bool shouldDraw(BuddyTreeItem* bti);
	bool isVisible(wxCoord & y, wxCoord height);
	wxCoord toScrolledPosition(wxCoord y);
	wxCoord getPosition(TreeItem* item);

	void offlineBuddiesToOfflineGroup(GroupTreeItem* gti);
	void buddiesToRootNoGroup(GroupTreeItem* gti);
	void setGroupExpended(GroupTreeItem* gti, bool extended);
	void calculateSize(GroupTreeItem* gti, wxPoint & curPos);
	void updateSize();
	bool removeBuddy(Buddy* buddy, GroupTreeItem* gti);

	inline bool treatAsOffline(const Status & status){
		return status==OFFLINE || (treatUnknownAsOffline && status==UNKNOWN && status!=INVISIBLE);
	}

private:
	DECLARE_EVENT_TABLE()
};

}

#endif /*BUDDYTREELIST_H_*/
